package com.ihrm.employee;


import com.ihrm.common.shiro.realm.IhrmRealm;
import com.ihrm.common.shiro.session.CustomSessionManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfiguration {
    
    @Value("${spring.redis.host}")
    private String host;
    
    @Value("${spring.redis.port}")
    private int port;
    
    /**
     * 配置自定义的Realm
     */
    @Bean
    public IhrmRealm getRealm(){
        return new IhrmRealm();
    }
    
    /**
     * 配置安全管理器
     */
    @Bean
    public SecurityManager securityManager(){
        /**
         * 使用默认的安全管理器
         */
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        /**
         * 自定义session管理器 使用redis
         */
        securityManager.setSessionManager(sessionManager());
        /**
         * 自定义缓存实现，使用redis
         */
        securityManager.setCacheManager(cacheManager());
        /**
         * 将自定义的realm交给安全管理器统一调度管理
         */
        securityManager.setRealm(getRealm());
        return securityManager;
    }
    
    
    /**
     * Filter工厂，设置对应的过滤条件和跳转条件
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){
        /**
         * 创建shiro过滤器工厂
         */
        ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();
    
        /**
         * 设置安全管理器
         */
        filterFactoryBean.setSecurityManager(securityManager);
    
        /**
         * 通用配置(配置登录页面，登录成功页面，验证未成功页面)
         */
        filterFactoryBean.setLoginUrl("/autherror?code=1");//设置登录页面
        filterFactoryBean.setUnauthorizedUrl("/autherror?code=2");//授权失败跳转页面
    
        /**
         * 配置过滤器集合
         *
         * key :访问连接
         *          支持通配符形式
         * value :过滤器类型
         *          shiro常用过滤器
         *             anno  : 匿名访问(表明此链接所有人都可以访问)
         *             authc : 认证后访问(表明此链接需登录认证成功后可以访问)
         */
        Map<String, String> filterMap = new LinkedHashMap<>();
    
        /**
         * 配置请求链接过滤器
         */
        filterMap.put("/frame/login","anon");
        filterMap.put("/autherror","anon");
        filterMap.put("/**","authc");
    
        /**
         * 设置过滤器
         */
        filterFactoryBean.setFilterChainDefinitionMap(filterMap);
        
        return filterFactoryBean;
        
    }
    
    
    /**
     * 配置shiro注解支持
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager());
        return advisor;
    }
    
    
    /**
     * 配置shiro redisManager
     */
    public RedisManager redisManager(){
        RedisManager redisManager = new RedisManager();
        redisManager.setHost(host);
        redisManager.setPort(port);
        return redisManager;
    }
    
    /**
     * cacheManager缓存 redis实现
     */
    public RedisCacheManager cacheManager(){
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(redisManager());
        return redisCacheManager;
    }
    
    /**
     * RedisSessionDAO shiro sessionDao层的实现 通过redis
     * 使用的是shiro-redis开源插件
     */
    public RedisSessionDAO redisSessionDAO(){
        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
        redisSessionDAO.setRedisManager(redisManager());
        return redisSessionDAO;
    }
    
    /**
     * shiro session的管理
     */
    public DefaultWebSessionManager sessionManager(){
        CustomSessionManager sessionManager = new CustomSessionManager();
        sessionManager.setSessionDAO(redisSessionDAO());
        return sessionManager;
    }
    
    
}
